home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / intrvews / xgrab.lha / xgrab / grabst / levels.c < prev    next >
C/C++ Source or Header  |  1990-03-06  |  10KB  |  368 lines

  1. /**
  2.    GRAB Graph Layout and Browser System
  3.  
  4.    Copyright (c) 1986, 1988 Regents of the University of California
  5.    Copyright (c) 1989, Tera Computer Company
  6.  **/
  7.  
  8.   /* levels.c -- routines to manipulate the level structure of the digraph */
  9.  
  10. #include "malloc.h"
  11. #include <string.h>
  12.  
  13. #include "attribute.h"
  14. #include "digraph.h"
  15. #include "debug.h"
  16.  
  17. #define DUMMY_SHAPE    POINT        /* default shape for dummy */
  18. #define    DUMMY_BRUSH    SOLIDB        /* default brush for dummy */
  19. #define    DUMMY_COLOR    BLACK        /* default color for dummy */
  20.  
  21. VERTEX *insert_vertex();
  22. NODE *insert_node();
  23. LEVEL *find_level();
  24. char **dispose_out_edge();
  25.  
  26. add_level(digraph, members)
  27. DIGRAPH *digraph;
  28. SET *members;     /* members of the level */
  29.   /* add_level adds a new level to digraph with the vertices in members. */
  30. {
  31.     VNO vno;        /* each vertex number */
  32.     LEVEL *level;   /* the new level */
  33.  
  34.     new(level, LEVEL);
  35.     Prev_level(level) = NULL;
  36.     Next_level(level) = digraph->levels;   /* link in at the head */
  37.     digraph->levels = level;
  38.  
  39.     if (Next_level(level) != NULL)         /* fix previous of next */
  40.     {
  41.         Prev_level(Next_level(level)) = level;
  42.     }
  43.     else                                   /* this is the last level */
  44.     {
  45.         Last_level(digraph) = level;
  46.     }
  47.  
  48.     Order(level) = NULL;
  49.     Lno(level) = 0;    /* don't know level number yet */
  50.     Num_cross(level) = -1;          /* no crossings calculated yet */    
  51.     init_set(Members(level));
  52.  
  53.     each_element(members, vno)
  54.     loop
  55.           /* add a non-dummy member */
  56.         add_member(digraph, level, vno, NORMAL);
  57.     endloop
  58. } /* add_level */
  59.  
  60. add_dummy(digraph, new_level, vno, ante_set) 
  61. DIGRAPH *digraph;
  62. LEVEL *new_level;      /* level to put the dummy on */
  63. VNO vno;               /* succedent of the dummy */
  64. SET *ante_set;         /* antecedents of the dummy */
  65.   /**
  66.      add_dummy adds dummy nodes to new_level with succedent vno and antecedents
  67.      in ante_set.  If vno has no succedents, then vno itself is moved from its 
  68.      current level to new_level instead of creating dummies.
  69.    **/
  70. {
  71.     char name[100];        /* name of the dummy */
  72.     NODE *dummy_node;
  73.     VERTEX *dummy_vertex;
  74.     VNO dummy_vno;         /* the dummy vno */
  75.     VNO from_vno;          /* each antecedent of dummy */
  76.     int sub_num;      /* counter for more than one dummy */
  77.     int i;
  78.     char **attr;
  79.  
  80.     if (empty(Succ_set(Node(digraph, vno))) &&
  81.         equal(Ante_set(Node(digraph, vno)), ante_set))
  82.     {
  83.         LEVEL *vno_level;      /* level vno is on */
  84.  
  85.           /* move to new_level */
  86.         vno_level = find_level(digraph, vno);    /* get vno's level */
  87.         move_member(digraph, vno_level, vno, new_level);
  88.         return;
  89.     }
  90.  
  91.       /* otherwise create a dummy */
  92.     Last_dummy(Member(digraph, vno))++;   /* adding another dummy */
  93.     sub_num = 0;              /* for more than one dummy */
  94.  
  95.     each_element(ante_set, from_vno)      /* fix up antecedents */
  96.     loop
  97.         sprintf(name, "->%s.%d.%d", Name(Node(digraph, vno)), 
  98.             Last_dummy(Member(digraph, vno)), sub_num++);
  99.  
  100.           /* create the array of (null) attributes */
  101.         attr = (char **) malloc(NNodeAttr(digraph) * sizeof(char *));
  102.  
  103.         for (i = 0; i < NNodeAttr(digraph); i++)
  104.         {
  105.             strsave(attr[i], NULL_STRING);
  106.         }
  107.  
  108.           /* create a dummy. */
  109.         dummy_vertex = insert_vertex(digraph, name);
  110.         dummy_node = insert_node(digraph, dummy_vertex, attr, DUMMY_SHAPE,
  111.                            DUMMY_BRUSH, DUMMY_COLOR, TRUE, 0, 0, DUMMY);
  112.       /**
  113.          for multi-graph and two-way edges:  All edges between a pair
  114.          of nodes follow the same path, including dummy nodes.  So
  115.          dummy nodes are made wider to support more than one distinct 
  116.          in and out edge.
  117.        **/
  118.     Half_width(dummy_node) += EDGE_GAP * 
  119.                     max_edges(Node(digraph, from_vno),
  120.                           Node(digraph, vno)) / 2;
  121.         dummy_vno = Vno(dummy_node);
  122.  
  123.         remove_element(Succ_set(Node(digraph, from_vno)), vno);
  124.         add_element(Succ_set(Node(digraph, from_vno)), dummy_vno);
  125.  
  126.         add_element(Ante_set(Node(digraph, dummy_vno)), from_vno);
  127.         add_element(Succ_set(Node(digraph, dummy_vno)), vno);
  128.  
  129.         remove_element(Ante_set(Node(digraph, vno)), from_vno);  
  130.                             /* shorten span */
  131.         add_element(Ante_set(Node(digraph, vno)), dummy_vno);
  132.  
  133.           /* now add a dummy member */
  134.         add_member(digraph, new_level, dummy_vno, DUMMY); 
  135.  
  136.         if (debug)
  137.         {
  138.         printf("\nadd_dummy:  created dummy '%s'\n", 
  139.            Name(Node(digraph, dummy_vno)));
  140.         printf("   Succedents: ");
  141.         print_set(digraph, Succ_set(Node(digraph, dummy_vno)));
  142.         printf("\n   Antecedents: ");
  143.         print_set(digraph, Ante_set(Node(digraph, dummy_vno)));
  144.         printf("\n");
  145.         }
  146.     endloop
  147. } /* add_dummy */
  148.  
  149. add_member(digraph, level, vno, status)    
  150. DIGRAPH *digraph;
  151. LEVEL *level;     /* level for new member */
  152. VNO vno;          /* vno of new member */
  153. STATUS status;    /* status of new member */
  154.   /* add_member adds a new member to level. */
  155. {
  156.     MEMBER *member;    /* the new member */
  157.  
  158.     member = Member(digraph, vno);
  159.     Next_member(member) = Order(level);
  160.     Order(level) = member;
  161.     Prev_member(member) = NULL;
  162.  
  163.     if (Next_member(member) != NULL)
  164.     {
  165.         Prev_member(Next_member(member)) = member;
  166.     }
  167.  
  168.     Status(member) = status;
  169.     Bc(member, UP) = Bc(member, DOWN) = NO_BC;
  170.     Level_no(member) = Lno(level); 
  171.     add_element(Members(level), vno);
  172. } /* add_member */
  173.  
  174. remove_member(digraph, level, vno)    
  175. DIGRAPH *digraph;
  176. LEVEL *level;
  177. VNO vno;
  178.   /**
  179.      remove_member removes the member for vno from level.  If vno is not
  180.      a member of level, an error occurs.
  181.    **/
  182.     MEMBER *member;
  183.  
  184.     member = Member(digraph, vno);
  185.  
  186.     if (Prev_member(member) == NULL)            /* new head */
  187.     {
  188.         Order(level) = Next_member(member);
  189.     }
  190.     else 
  191.     {
  192.         Next_member(Prev_member(member)) = Next_member(member);
  193.     }
  194.  
  195.     if (Next_member(member) != NULL)
  196.     {
  197.         Prev_member(Next_member(member)) = Prev_member(member);
  198.     }
  199.  
  200.     Next_member(member) = Prev_member(member) = NULL;
  201.     remove_element(Members(level), vno);
  202. } /* remove_member */
  203.  
  204. move_member(digraph, from_level, vno, to_level)    
  205. DIGRAPH *digraph;
  206. LEVEL *from_level;
  207. VNO vno;
  208. LEVEL *to_level;
  209.   /* move_member moves vno from from_level to to_level. */
  210. {
  211.     MEMBER *member;
  212.  
  213.     member = Member(digraph, vno);
  214.     remove_member(digraph, from_level, vno);    /* remove from previous level */
  215.     add_member(digraph, to_level, vno, Status(member));
  216. } /* move_member */
  217.  
  218. LEVEL *find_level(digraph, vno)
  219. DIGRAPH *digraph;
  220. VNO vno;
  221.   /**
  222.      find_level finds the level in which vno is a member in digraph.  If there
  223.      is no such level, NULL is returned.
  224.    **/
  225. {
  226.     LEVEL *level;  /* each level */
  227.  
  228.     if (debug)
  229.     {
  230.         printf("\nfind_level:  looking for level of '%s'\n", 
  231.            Name(Node(digraph, vno)));
  232.     }
  233.  
  234.     each_level(digraph, level)
  235.     loop
  236.         if (in(Members(level), vno))
  237.         {
  238.           return(level);
  239.     }
  240.     endloop
  241.     return(NULL);
  242. } /* find_level */
  243.  
  244. remove_long_spans(digraph)
  245. DIGRAPH *digraph;
  246.   /**
  247.      remove_long_spans follows dummy edges from NORMAL node to NORMAL node and
  248.      removes the long span from the appropriate successor and ancestor sets. 
  249.    **/
  250. {
  251.     NODE *node, *next;
  252.     VNO vno;
  253.     NODE *next_dummy();
  254.  
  255.     each_node(digraph, node)
  256.     loop
  257.         if (Status(node) != NORMAL)
  258.     {
  259.             continue;
  260.     }
  261.  
  262.     each_element(Succ_set(node), vno)
  263.     loop
  264.         next = Node(digraph, vno);
  265.  
  266.         if (!Is_dummy(next))
  267.         {
  268.         continue;
  269.         }
  270.  
  271.         while (Is_dummy(next))
  272.         {
  273.         next = next_dummy(digraph, next);
  274.         }
  275.  
  276.         if (Status(next) != NORMAL)
  277.         {
  278.         continue;
  279.         }
  280.  
  281.           /**
  282.          next is now the next NORMAL node after a series
  283.              of dummy nodes
  284.            **/
  285.         remove_element(Succ_set(node), Vno(next));
  286.         remove_element(Ante_set(next), Vno(node));
  287.     endloop
  288.     endloop
  289. } /* remove_long_spans */
  290.  
  291. OUTEDGE *get_edge();
  292. INEDGE *get_in_edge();
  293.  
  294. reverse_edge(digraph, vno, root_vno, ord)
  295. DIGRAPH *digraph;
  296. VNO vno;        /* last vno before cycle */
  297. VNO root_vno;        /* vertex # of successor to vno, causing cycle */
  298. int ord;        /* ordinality of the edge */
  299.   /**
  300.      reverse-edge removes an edge and its associated set members, and adds
  301.      a new edge, with the same attributes, going in the opposite direction.
  302.    **/
  303. {
  304.     NODE *node, *root_node;
  305.     int errval;            /* 0 if insert_edge successful */
  306.     NODE *realnode, *realroot;
  307.     int realord;
  308.     INEDGE *inedge;
  309.     OUTEDGE *outedge;
  310.     BRUSH brush;
  311.     COLOR color;
  312.     char **attr;
  313.     BOOL reverse;
  314.  
  315.     node = Node(digraph, vno);
  316.     root_node = Node(digraph, root_vno);
  317.  
  318.     if (Is_dummy(node) || Is_dummy(root_node))
  319.     {
  320.     return;
  321.     }
  322.     
  323.     outedge = get_edge(digraph, node, root_node, ord);
  324.     inedge = get_in_edge(digraph, node, root_node, ord);
  325.       /**
  326.      nodes could be coalescers, so we need to get the real 
  327.      endpoints of the edge.
  328.        **/
  329.     realroot = Node(digraph, To_vno(outedge));
  330.     realnode = Node(digraph, From_vno(inedge));
  331.     reverse = !Edge_reversed(outedge);
  332.     realord = Ord(outedge);
  333.  
  334.     if (debug)
  335.     {
  336.     printf("Reversing Edge: (%s, %s)\n", Name(node), Name(root_node));
  337.     }
  338.  
  339.       /**
  340.      note: normally, you'd have to check if this were the last edge
  341.      between the two nodes before you removed the link.  But we know 
  342.      that all edges between two nodes go in the same direction, so if 
  343.      we're reversing this edge, we're reversing all the edges from node 
  344.      to root_node, and we can safely remove the link.
  345.        **/
  346.     remove_link(node, root_node);
  347.     attr = dispose_out_edge(realnode, Vno(realroot), realord, &brush, 
  348.                 &color);
  349.     dispose_in_edge(realroot, Vno(realnode), realord);
  350.     errval = insert_edge(digraph, Vno(realroot), Vno(realnode), attr, brush, 
  351.              color);
  352.     realord = max_edges(realroot, realnode);
  353.       /* ord has now changed */
  354.  
  355.     if (errval != 0) 
  356.     {
  357.     PrintError("reverse_edge: illegal vertex number");
  358.     } 
  359.     else 
  360.     {    
  361.     outedge = get_edge(digraph, realroot, realnode, realord);
  362.     inedge = get_in_edge(digraph, realroot, realnode, realord);
  363.     Edge_reversed(outedge) = reverse;
  364.     Edge_reversed(inedge) = reverse;
  365.     }
  366. }  /* reverse_edge */
  367.